﻿using System;
using System.Data;
using System.Data.SqlClient;
using CentroVentas.Clases.Utiles;

namespace CentroVentas.Clases
{
    /// <summary>
    /// Clase que permite el trabajo con los usuarios dentro del sistema.
    /// </summary>
    class Usuarios
    {

        #region Objetos
        // Objeto para sentenciar la BD.
        DataBase bd = new DataBase();
        #endregion

        #region Variables

        int _id, _tipousuario;
        bool _activo;
        string _rut,_nombre, _password, _email;

        #endregion

        #region Propiedades

        /// <summary>
        /// Obtiene o establece el Id a consultar del usuario.
        /// </summary>
        public int Id {
            get
            {
                return _id;
            }

            set
            {
                if (this.existeUsuario(value))
                {
                    _id = value;
                }
                else
                {
                    throw new Exception("Usuario no existe");
                }
            }
        }

        /// <summary>
        /// Obtiene o establece el tipo de usuario que es el Id especificado.
        /// </summary>
        public int TipoUsuario {

            get
            {
                try
                {
                    DataSet dset = new DataSet();
                    bd.dadap.SelectCommand = new SqlCommand("SELECT tipousuario FROM usuario WHERE usuario.id = @id", bd.Conn);
                    bd.dadap.SelectCommand.Parameters.Add(new SqlParameter("@id", SqlDbType.Int)).Value = _id;
                    bd.dadap.Fill(dset, "TipoUsuario");
                    return Convert.ToInt32(dset.Tables["TipoUsuario"].Rows[0].ItemArray[0].ToString());
                }
                catch (Exception)
                {
                    throw;
                }
            }

            set
            {
                try
                {
                    bd.conectar();
                    bd.dadap.UpdateCommand = new SqlCommand("UPDATE usuario SET tipousuario = @tipousu WHERE id = @id", bd.Conn);
                    bd.dadap.UpdateCommand.Parameters.Add(new SqlParameter("@tipousuario", SqlDbType.Int)).Value = value;
                    bd.dadap.UpdateCommand.Parameters.Add(new SqlParameter("@id", SqlDbType.Int)).Value = _id;
                    bd.dadap.UpdateCommand.ExecuteNonQuery();
                    bd.desconectar();
                    _tipousuario = value;
                }
                catch (Exception)
                {
                    throw;
                }
            }
        }

        /// <summary>
        /// Obtiene ó establece el nombre de usuario que es el Id especificado.
        /// </summary>
        public string Nombre 
        {
            get
            {
                try
                {
                    DataSet dset = new DataSet();
                    bd.dadap.SelectCommand = new SqlCommand("SELECT rut FROM usuario WHERE usuario.id = @id", bd.Conn);
                    bd.dadap.SelectCommand.Parameters.Add(new SqlParameter("@id", SqlDbType.Int)).Value = _id;
                    bd.dadap.Fill(dset, "Rut");
                    return dset.Tables["Rut"].Rows[0].ItemArray[0].ToString();
                }
                catch (Exception)
                {
                    throw;
                }
            }

            set
            {
                if (!this.existeUsuario(value))
                {
                    try
                    {
                        bd.conectar();
                        bd.dadap.UpdateCommand = new SqlCommand("UPDATE usuario SET rut = @rut WHERE id = @id", bd.Conn);
                        bd.dadap.UpdateCommand.Parameters.Add(new SqlParameter("@rut", SqlDbType.VarChar)).Value = value;
                        bd.dadap.UpdateCommand.Parameters.Add(new SqlParameter("@id", SqlDbType.Int)).Value = _id;
                        bd.dadap.UpdateCommand.ExecuteNonQuery();
                        bd.desconectar();
                        _rut = value;
                    }
                    catch (Exception)
                    {
                        throw;
                    }
                }
                else
                {
                    throw new Exception("Nombre de usuario ya existe en la BD.");
                }
            }
        }

        /// <summary>
        /// Obtiene o establece el nombre real de usuario del Id especificado.
        /// </summary>
        public string NombreUsuario {  get
            {
                try
                {
                    DataSet dset = new DataSet();
                    bd.dadap.SelectCommand = new SqlCommand("SELECT nombreReal FROM usuario WHERE usuario.id = @id", bd.Conn);
                    bd.dadap.SelectCommand.Parameters.Add(new SqlParameter("@id", SqlDbType.Int)).Value = _id;
                    bd.dadap.Fill(dset, "Nombre");
                    return dset.Tables["Nombre"].Rows[0].ItemArray[0].ToString();
                }
                catch (Exception)
                {
                    throw;
                }
            }

            set
            {
                if (!this.existeUsuario(value))
                {
                    try
                    {
                        bd.conectar();
                        bd.dadap.UpdateCommand = new SqlCommand("UPDATE usuario SET nombreReal = @nombre WHERE id = @id", bd.Conn);
                        bd.dadap.UpdateCommand.Parameters.Add(new SqlParameter("@nombre", SqlDbType.VarChar)).Value = value;
                        bd.dadap.UpdateCommand.Parameters.Add(new SqlParameter("@id", SqlDbType.Int)).Value = _id;
                        bd.dadap.UpdateCommand.ExecuteNonQuery();
                        bd.desconectar();
                        _nombre = value;
                    }
                    catch (Exception)
                    {
                        throw;
                    }
                }
                else
                {
                    throw new Exception("Nombre de usuario ya existe en la BD.");
                }
            } }

        /// <summary>
        /// Obtiene ó establece la password del usuario especificado por la Id.
        /// </summary>
        public string Password 
        {
            get
            {
                try
                {
                    DataSet dset = new DataSet();
                    bd.dadap.SelectCommand = new SqlCommand("SELECT pswd FROM usuario WHERE usuario.id = @id", bd.Conn);
                    bd.dadap.SelectCommand.Parameters.Add(new SqlParameter("@id", SqlDbType.Int)).Value = _id;
                    bd.dadap.Fill(dset, "Password");
                    return dset.Tables["Password"].Rows[0].ItemArray[0].ToString();
                }
                catch (Exception)
                {
                    throw;
                }
            }

            set
            {
                try
                {
                    bd.conectar();
                    bd.dadap.UpdateCommand = new SqlCommand("UPDATE usuario SET pswd = @Password WHERE id = @id", bd.Conn);
                    bd.dadap.UpdateCommand.Parameters.Add(new SqlParameter("@pswd", SqlDbType.VarChar)).Value = Seguridad.generarClaveSHA512(value);
                    bd.dadap.UpdateCommand.Parameters.Add(new SqlParameter("@id", SqlDbType.Int)).Value = _id;
                    bd.dadap.UpdateCommand.ExecuteNonQuery();
                    bd.desconectar();
                    _password = value;
                }
                catch (Exception)
                {
                    throw;
                }
            }
        }

        /// <summary>
        /// Obtiene o establece el correo electrónico del usuario especificado por la Id.
        /// </summary>
        public string Email 
        {
            get
            {
                try
                {
                    DataSet dset = new DataSet();
                    bd.dadap.SelectCommand = new SqlCommand("SELECT email FROM usuario WHERE usuario.id = @id", bd.Conn);
                    bd.dadap.SelectCommand.Parameters.Add(new SqlParameter("@id", SqlDbType.Int)).Value = _id;
                    bd.dadap.Fill(dset, "Email");
                    return dset.Tables["Email"].Rows[0].ItemArray[0].ToString();
                }
                catch (Exception)
                {
                    throw;
                }
            }

            set
            {
                try
                {
                    bd.conectar();
                    bd.dadap.UpdateCommand = new SqlCommand("UPDATE usuario SET email = @email WHERE id = @id", bd.Conn);
                    bd.dadap.UpdateCommand.Parameters.Add(new SqlParameter("@email", SqlDbType.VarChar)).Value = value;
                    bd.dadap.UpdateCommand.Parameters.Add(new SqlParameter("@id", SqlDbType.Int)).Value = _id;
                    bd.dadap.UpdateCommand.ExecuteNonQuery();
                    bd.desconectar();
                    _email = value;
                }
                catch (Exception)
                {
                    throw;
                }
            }
        }

        /// <summary>
        /// Obtiene o establece el estado actual del usuario dentro del sistema.
        /// </summary>
        public bool Activo 
        {
            get
            {
                try
                {
                    DataSet dset = new DataSet();
                    bd.dadap.SelectCommand = new SqlCommand("SELECT activo FROM usuario WHERE usuario.id = @id", bd.Conn);
                    bd.dadap.SelectCommand.Parameters.Add(new SqlParameter("@id", SqlDbType.Int)).Value = _id;
                    bd.dadap.Fill(dset, "Activo");
                    if (Convert.ToInt32(dset.Tables["Activo"].Rows[0].ItemArray[0].ToString()) == 1) return true;
                    return false;
                }
                catch (Exception)
                {
                    return false;
                }
            }

            set
            {
                try
                {
                    int valor = 0;
                    bd.conectar();
                    bd.dadap.UpdateCommand = new SqlCommand("UPDATE usuario SET activo = @tipousu WHERE id = @id", bd.Conn);
                    if (value){
                        valor = 1;
                    } 
                    else
                    {
                        valor = 0;
                    }
                    bd.dadap.UpdateCommand.Parameters.Add(new SqlParameter("@activo", SqlDbType.Int)).Value = valor;
                    bd.dadap.UpdateCommand.Parameters.Add(new SqlParameter("@id", SqlDbType.Int)).Value = _id;
                    bd.dadap.UpdateCommand.ExecuteNonQuery();
                    bd.desconectar();
                    _activo = value;
                }
                catch (Exception)
                {
                    throw;
                }
            }
        }

        #endregion
        
        #region Constructores
        /// <summary>
        /// Construye el objeto solo para acceder a las clases estáticas.
        /// </summary>
        public Usuarios() { }

        /// <summary>
        /// Construye el objeto que se inicializa con el nombre y establece la Id del usuario para posteriores búsquedas de datos.
        /// </summary>
        public Usuarios(string nombre)
        {
            try
            {
                if (!this.existeUsuario(nombre))
                {
                    throw new Exception("Usuario no existe");
                }
                else
                {
                    _id = GetIdUsuario(nombre);
                }                
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        public Usuarios(int id)
        {
            _id = id;
        }

        #endregion

        #region MetodosEstaticos

        /// <summary>
        /// Obtengo los usuarios para ocuparlos en un AutoCompleteTextBox
        /// </summary>
        /// <param name="textBox">Control a Usar</param>
        public static void GetUsuariosTextBox(System.Windows.Forms.TextBox textBox)
        {
            try
            {
                //Obtención de los datos.
                DataBase db = DataBase.GetInstance(); // Creo un objeto Database para adquirir los datos de la BD.
                System.Data.DataSet ds = new System.Data.DataSet(); // DataSet para almacenar los datos obtenidos.
                string consulta = "SELECT rut FROM usuario WHERE activo = 1"; // Seleccionar todos los nombres de usuario que sean distintos al de el ADMIN y que el estado sea activo
                db.dadap.SelectCommand = new System.Data.SqlClient.SqlCommand(consulta, db.Conn); // Obtengo los datos desde la BD.
                db.dadap.Fill(ds, "usuarios"); // Lleno los datos obtenidos en el DataSet.
                // Llenado del TextBox
                textBox.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.CustomSource;
                textBox.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.Append;
                System.Windows.Forms.AutoCompleteStringCollection aColl = new System.Windows.Forms.AutoCompleteStringCollection();
                foreach (System.Data.DataRow dr in ds.Tables["usuarios"].Rows)
                {
                    aColl.Add((string)dr[0]);
                }
                textBox.AutoCompleteCustomSource = aColl;

            }
            catch (Exception)
            {
                
                throw;
            }

            
        }

        /// <summary>
        /// Crea un usuario con los datos otorgados.
        /// </summary>
        /// <param name="nombre"></param>
        /// <param name="password"></param>
        /// <param name="email"></param>
        /// <param name="tipousuario"></param>
        /// <returns>Booleano dependiendo de si fue correctamente ingresado.</returns>
        public static bool CrearUsuario(string rut,string nombre, string password, string email, int tipousuario)
        {
            // INSERT INTO usuario VALUES('ADMIN','password',1,'email@email.com',1);
            try
            {
                DataBase db = DataBase.GetInstance();
                db.dadap.InsertCommand = new SqlCommand("INSERT INTO usuario VALUES(@rut,@nombre,@password,@tipousuario,@correo,1)", db.Conn);
                db.dadap.InsertCommand.Parameters.Add(new SqlParameter("@rut", SqlDbType.VarChar)).Value = rut;
                db.dadap.InsertCommand.Parameters.Add(new SqlParameter("@nombre", SqlDbType.VarChar)).Value = nombre;
                db.dadap.InsertCommand.Parameters.Add(new SqlParameter("@password", SqlDbType.VarChar)).Value = Seguridad.generarClaveSHA512(password);
                db.dadap.InsertCommand.Parameters.Add(new SqlParameter("@tipousuario", SqlDbType.Int)).Value = tipousuario;
                db.dadap.InsertCommand.Parameters.Add(new SqlParameter("@correo", SqlDbType.VarChar)).Value = email;
                db.dadap.InsertCommand.ExecuteNonQuery();

                Usuarios usu = new Usuarios(rut);
                if (Permisos.CrearFunciones(usu.Id))
                    return true;                

                return false;
            }
            catch (Exception ex)
            {
                Utilidades.mensaje(TipoMensaje.ERROR, ex.Message, 2);
                return false;
            }
        }


        public static bool ModificarUsuario(string rut, int tipousuario) 
        {
            try
            {
                DataBase db = DataBase.GetInstance();
                if (db.conectar())
                {
                    string consulta;
                    consulta = "UPDATE usuario SET usuario.tipousuario ="+tipousuario+"WHERE usuario.rut='"+rut+"'";
                    db.dadap.InsertCommand = new SqlCommand(consulta,db.Conn);
                    db.dadap.InsertCommand.ExecuteNonQuery();
                    db.desconectar();
                    return true;
                }
                else
                {
                    Utilidades.mensaje(TipoMensaje.ERROR, "No se pudo conectar a la BD.", 3);
                    return false;
                }
            }
            catch (Exception ex)
            {
                Utilidades.mensaje(TipoMensaje.ERROR, ex.Message, 2);
                return false;
            }
        }

        public static bool DesactivarUsuario(string rut)
        {
            DataBase db = DataBase.GetInstance();
            try
            {              
                    string consulta;
                    consulta = "UPDATE usuario SET usuario.activo = 2 WHERE usuario.rut = @rut";
                    db.dadap.InsertCommand = new SqlCommand(consulta, db.Conn);
                    db.dadap.InsertCommand.Parameters.Add(new SqlParameter("@rut", SqlDbType.VarChar)).Value = rut;
                    db.dadap.InsertCommand.ExecuteNonQuery();
                    return true;
              
            }
            catch (Exception ex)
            {
                Utilidades.mensaje(TipoMensaje.ERROR, ex.Message, 100);
                return false;
            }
        }

       

        public static bool ExisteUsuario(String Rut)
        {
            try
            {
                DataBase db = new DataBase();
                DataSet ds =new DataSet();
                db.dadap.SelectCommand = new SqlCommand("SELECT COUNT (id) FROM usuario WHERE rut = @rut", db.Conn);
                db.dadap.SelectCommand.Parameters.Add(new SqlParameter("@rut", SqlDbType.VarChar)).Value = Rut;
                db.dadap.Fill(ds, "ExisteRut");
                if (Convert.ToInt32(ds.Tables["ExisteRut"].Rows[0].ItemArray[0]) == 1) return true;
                return false;
            }
            catch (Exception)
            {

                Utilidades.mensaje(TipoMensaje.ERROR, "No se pudo obtener el dato.",6);
                return false;
            }

        }
        public static DataSet GetUsuariosComboBox()
        {
            try
            {
                DataBase db = DataBase.GetInstance(); // Creo un objeto Database para adquirir los datos de la BD.
                System.Data.DataSet ds = new System.Data.DataSet(); // DataSet para almacenar los datos obtenidos.
                string consulta = "SELECT id,rut FROM usuario"; // Seleccionar todos los nombres de usuario que sean distintos al de el ADMIN y que el estado sea activo
                db.dadap.SelectCommand = new System.Data.SqlClient.SqlCommand(consulta, db.Conn); // Obtengo los datos desde la BD.
                db.dadap.Fill(ds, "usuarios"); // Lleno los datos obtenidos en el DataSet.
                return ds;
            }
            catch (Exception)
            {
                
                throw;
            }
        }

        public static DataSet GetTipoUsuarioComboBox()
        {
            try
            {
                DataBase db = DataBase.GetInstance();
                DataSet ds = new DataSet();
                string consulta = "SELECT id,descripcion FROM tipousuario WHERE descripcion != 'ADMINISTRADOR'";
                db.dadap.SelectCommand = new System.Data.SqlClient.SqlCommand(consulta, db.Conn);
                db.dadap.Fill(ds, "TipoUsuarios");
                return ds;

            }
            catch (Exception)
            {
                Utilidades.mensaje(TipoMensaje.ERROR, "ex", 200);
                throw new Exception("No se pudo rescatar el tipo de usuario.");
            }

        }
        public static DataSet GetListarUsuarios(bool VerSoloActivos)
        {
                DataBase db = new DataBase();
                DataSet ds = new DataSet();
                string consulta;
                consulta = "SELECT usuario.id AS 'ID', usuario.rut AS 'RUT',usuario.nombreReal AS 'NOMBRE', tipousuario.descripcion AS 'TIPO USUARIO',usuario.email AS 'EMAIL', estado.descripcion AS 'ESTADO' FROM estado,usuario,tipousuario WHERE usuario.tipousuario = tipousuario.id ";
                try
                {
                    if (VerSoloActivos)
                        consulta += "AND usuario.activo = estado.id AND usuario.activo = 1 ";

                    db.dadap.SelectCommand = new SqlCommand(consulta, db.Conn);
                    db.dadap.Fill(ds, "usuarios");
                    return ds;
                }
                catch (Exception ex)
                {
                    System.Windows.Forms.MessageBox.Show(ex.Message);
                    throw;
                }
        }

        public static string GetTipoUsuario(int id)
        {
            try
            {
                //Obtención de los datos.
                DataBase db = DataBase.GetInstance(); // Creo un objeto Database para adquirir los datos de la BD.
                DataSet ds = new DataSet(); // DataSet para almacenar los datos obtenidos.
                string consulta = "SELECT tipousuario.descripcion FROM tipousuario WHERE id = " + id; 
                db.dadap.SelectCommand = new System.Data.SqlClient.SqlCommand(consulta, db.Conn); // Obtengo los datos desde la BD.
                db.dadap.Fill(ds, "usuarios"); // Lleno los datos obtenidos en el DataSet.
                return ds.Tables["usuarios"].Rows[0].ItemArray[0].ToString();
            }
            catch (Exception)
            {
                
                throw;
            }
        }
        
      
        #endregion

        #region MetodosPrivados

        /// <summary>
        /// Compruebo mediante un ID de usuario si este existe en la BD.
        /// </summary>
        /// <param name="id">Id de un usuario</param>
        /// <returns> Booleano dependiendo si existe (si=true/no=false)</returns>
        private bool existeUsuario(int id){
            try 
            {	        
                DataSet ds = new DataSet();
                bd.dadap.SelectCommand = new SqlCommand("SELECT COUNT(id) FROM usuario WHERE usuario.id = @id",bd.Conn);
                bd.dadap.SelectCommand.Parameters.Add(new SqlParameter("@id",SqlDbType.Int)).Value = id;
                bd.dadap.Fill(ds,"existeusuario");
                if(Convert.ToInt32(ds.Tables["existeusuario"].Rows[0].ItemArray[0]) == 1) return true;
                return false;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// Compruebo mediante el nombre de usuario si este existe en la BD.
        /// </summary>
        /// <param name="nombre">Nombre de usuario a comprobar.</param>
        /// <returns>Booleano dependiendo si existe (si=true/no=false)</returns>
        private bool existeUsuario(string rut)
        {
            try
            {
                DataSet ds = new DataSet();
                bd.dadap.SelectCommand = new SqlCommand("SELECT COUNT(rut) FROM usuario WHERE rut = @rut", bd.Conn);
                bd.dadap.SelectCommand.Parameters.Add(new SqlParameter("@rut", SqlDbType.VarChar)).Value = rut;
                bd.dadap.Fill(ds, "existeusuario");
                if (Convert.ToInt32(ds.Tables["existeusuario"].Rows[0].ItemArray[0]) == 1) return true;
                return false;
            }
            catch (Exception)
            {
                return true;
            }
        }

        private int GetIdUsuario(string rut)
        {
            try
            {
                DataSet dset = new DataSet();
                bd.dadap.SelectCommand = new SqlCommand("SELECT usuario.id FROM usuario WHERE usuario.rut = @rut", bd.Conn);
                bd.dadap.SelectCommand.Parameters.Add(new SqlParameter("@rut", SqlDbType.VarChar)).Value = rut;
                bd.dadap.Fill(dset, "usuario");
                return Convert.ToInt32(dset.Tables["usuario"].Rows[0].ItemArray[0].ToString());
            }
            catch (Exception)
            {
                return 0;
                throw;
            }
        }
        #endregion

    }
}
